﻿using FFmpeg.AutoGen;
using NAudio.Wave;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using VideoPlayer.FFmpegHandle;

namespace VideoPlayer
{
    public partial class Test3 : Form
    {
        public Test3()
        {
            InitializeComponent();

            //激活双缓冲技术
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.DoubleBuffer, true);
        }
        Thread thPlayer;
        private void Test3_Load(object sender, EventArgs e)
        {
            FFmpegBinariesHelper.RegisterFFmpegBinaries();
            Console.WriteLine($"FFmpeg version info: {ffmpeg.av_version_info()}");
            waveOut = new WaveOut();
            bufferedWaveProvider = new BufferedWaveProvider(new WaveFormat());
            waveOut.Init(bufferedWaveProvider);
            waveOut.Play();
        }
        //播放状态
        private bool isPlaying = false;

        //缓存时间（ms）
        const int BUFFER_DURATION = 2000;

        //NAudio音频播放组件
        private WaveOut waveOut;
        private BufferedWaveProvider bufferedWaveProvider;

        private void Button1_Click(object sender, EventArgs e)
        {
            button1.Enabled = false;
            if (thPlayer != null)
            {
                thPlayer = null;
            }
            else
            {
                thPlayer = new Thread(DeCoding);
                thPlayer.IsBackground = true;
                thPlayer.Start(textBox1.Text.Trim());
                button1.Text = "停止播放";
                button1.Enabled = true;
            }
        }

        /// 播放线程执行方法
        /// </summary>
        private unsafe void DeCoding(object str)
        {
            try
            {
                Console.WriteLine("DeCoding run...");
                play(str.ToString());

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
            finally
            {
                Console.WriteLine("DeCoding exit");
                this.Invoke(new MethodInvoker(() =>
                {
                    button1.Text = "开始播放";
                    button1.Enabled = true;
                }));
            }
        }
        StreamDecoder streamDecoder = null;
        /// <summary>
        /// 播放
        /// </summary>
        unsafe void play(string url)
        {
            isPlaying = true;

            streamDecoder = new StreamDecoder(url);

            var sourceSize = streamDecoder.FrameSize;
            var sourcePixelFormat = streamDecoder.PixelFormat;
            var destinationSize = sourceSize;
            var destinationPixelFormat = AVPixelFormat.AV_PIX_FMT_BGR24;
            var vfc = new VideoFrameConverter(sourceSize, sourcePixelFormat, destinationSize, destinationPixelFormat);
            TimeSpan audioMaxBufferedDuration = new TimeSpan(0, 0, 0, 0, BUFFER_DURATION); //音频最大缓冲时间
            if (numericUpDown1.InvokeRequired)
            {
                numericUpDown1.Invoke(new Action<long>(p =>
                {
                    numericUpDown1.Maximum = p / 1000;
                }), streamDecoder.m_Duration);
            }
            else
                numericUpDown1.Maximum = streamDecoder.m_Duration / 1000;
            while (isPlaying)
            {
                var timeSpan = new Stopwatch();
                timeSpan.Start();
                int i = streamDecoder.read_frame(); //读取一帧 1:音频 2:视频
                if (i == 1)
                {
                    if (bufferedWaveProvider.BufferedDuration.CompareTo(audioMaxBufferedDuration) > 0)
                    {
                        bufferedWaveProvider.ClearBuffer();
                    }

                    IntPtr audioFrame = (IntPtr)streamDecoder.get_audio_frame(); //一帧音频句柄
                    int bufSize = streamDecoder.get_audio_buffer_size(); //一帧音频占用大小
                    byte[] bytes = new byte[bufSize];
                    Marshal.Copy(audioFrame, bytes, 0, bufSize); //拷贝句柄中的音频到bytes
                    bufferedWaveProvider.AddSamples(bytes, 0, bufSize);//向缓存中添加音频样本
                }
                else if (i == 2)
                {
                    try
                    {
                        //var bitmap = new Bitmap(fFmpegDll.get_video_width(), fFmpegDll.get_video_height(),
                        //    fFmpegDll.get_linesize()[0], System.Drawing.Imaging.PixelFormat.Format24bppRgb, fFmpegDll.get_video_frame());

                        //var convertedFrame = vfc.Convert(frame);
                        //var bitmap = new Bitmap(convertedFrame.width, convertedFrame.height, convertedFrame.linesize[0]+1, System.Drawing.Imaging.PixelFormat.Format24bppRgb, (IntPtr)convertedFrame.data[0]);

                        var frame = streamDecoder.get_video_frame();
                        var bitmap = vfc.ConvertBitmap(frame);
                        if (metroPanel1.InvokeRequired)
                        {
                            metroPanel1.Invoke(new Action<Bitmap>(p =>
                            {
                                metroPanel1.BackgroundImage = p;
                            }), bitmap);
                        }
                        else
                        {
                            metroPanel1.BackgroundImage = bitmap;
                        }
                        timeSpan.Stop();
                        //Console.WriteLine();
                        //Thread.Sleep(1000 / 30);
                        if (((int)(1000 / streamDecoder.frame_rate) / 1 - (int)timeSpan.ElapsedMilliseconds - 1) > 0)
                            Thread.Sleep((int)(1000 / streamDecoder.frame_rate) / 1 - (int)timeSpan.ElapsedMilliseconds - 1);
                    }
                    catch (Exception ex)
                    { }
                }
                if (timeSpan.IsRunning)
                    timeSpan.Stop();
            }
        }

        private void Button2_Click(object sender, EventArgs e)
        {
            
        }

        private void Button3_Click(object sender, EventArgs e)
        {
            streamDecoder.JumpDate = (long)numericUpDown1.Value;
        }

        private void MetroPanel1_Paint(object sender, PaintEventArgs e)
        {

        }
    }
}
